package com.lagou.module4hw.hw56.server;

import com.lagou.module4hw.hw56.parsepackage.ParsePack;
import org.jetbrains.annotations.NotNull;


import java.io.*;
import java.net.Socket;
import java.nio.ByteBuffer;

/**
 * 服务器线程
 */
public class ServerReceive implements Runnable{

    //当前socket
    private Socket socket;

    //用户目录
    private String userDir;

    //用户名
    private String name;

    //构造方法
    public ServerReceive(Socket socket) {
        this.socket = socket;
    }

    //设置用户名
    public void setName(byte[] nameBytes,int size) {
        name = new String(nameBytes,0,size);
        //System.out.println("---------");
        System.out.println( " 上线了 " + name);
        //System.out.println("---------");
    }

    //返回用户目录
    public String getUserDir() {
        return userDir;
    }

    //设置用户目录
    public void setUserDir() {
        userDir = "D:\\"+"server\\" +name;
        File dir = new File(userDir);
        if(!dir.exists()){
            System.out.println("用户目录不存在，开始创建目录");
            //创建文件
            dir.mkdirs();
        }
    }

    @Override
    public void run() {

        BufferedInputStream bis = null;
        try {
            bis = new BufferedInputStream(socket.getInputStream());
            byte[] nameBytes = new byte[128];
            int res = bis.read(nameBytes);
            setName(nameBytes,res);

                while( true ){
                    //synchronized (socket){
                        //先读取包头
                        byte[] header = new byte[9];
                        if ( -1 == bis.read(header)){
                            //System.out.println("客户端已下线");
                            continue;
                        }
                        //第一包数据包的总大小
                        long firstPackSize = ParsePack.getPackSize(header);

                        if( ParsePack.isString(header) ){
                            //普通字符串
                            byte[] data = new byte[(int)firstPackSize];
                            bis.read(data);
                            String mesg = new String(data);
                            System.out.println("收到 " + name + " 发来: " + mesg );

                            //把客户发送的信息转发给其他客户
                            refernceMesg(ParsePack.pack("\t\t" + name +" --> " +mesg));
                            System.out.println("转发消息成功");

                            //判断是否下线
                            if("bye".equalsIgnoreCase(mesg)){
                                System.out.println(name + "下线了");
                                break;
                            }


                        }else {
                            //是文件，第一个包是文件头，先接收文件头，后接收文件内容
                            byte[] fileNameBytes = new byte[(int) firstPackSize];
                            //读取文件头第一包 1 + 8(文件名大小)+ 文件名 + 8(文件大小)
                            bis.read(fileNameBytes);
                            String fileName = new String(fileNameBytes);
                            System.out.println("文件名是: " + fileName);

                            //再读8个字节是文件大小
                            byte[] fileSizeBytes = new byte[8];
                            bis.read(fileSizeBytes);
                            long fileSize = ByteBuffer.wrap(fileSizeBytes).getLong();
                            System.out.println("文件的大小是: " + fileSize);


                            //开始读取具体文件内容
                            //创建文件输出流保存文件信息
                            setUserDir();
                            BufferedOutputStream bos = new BufferedOutputStream(
                                    new FileOutputStream(getUserDir() + "\\" + fileName));
                            //总共需要读取fileSize字节 一次读取1024个字节
                            byte[] dataBytes = new byte[1024];
                            long leftSize = fileSize;
                            long readSize = 0;
                            while (leftSize > 0) {
                                //读取readSize字节放到dataBytes中
                                readSize = bis.read(dataBytes);
                                //把读到的字节写入文件中
                                bos.write(dataBytes, 0, (int) readSize);
                                //文件总大小-当前读取的大小 = 还剩要读取的大小
                                leftSize -= readSize;
                            }
                            bos.flush();
                            System.out.println("接收文件成功 ");

                            //转发文件给其他客户端
                            referenceFile("file:" + getUserDir() + "/" + fileName);
                        }

                    //}
            }
        } catch (IOException e) {
            //e.printStackTrace();
            System.out.println("客户端下线了");
        } finally {
            if(bis != null) {
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            //删除socket
            synchronized (Server.lock){
                Server.socketList.remove(socket);
            }
        }
    }

    private void referenceFile(@NotNull String str) {

        String filedir = str.replace('\\', '/');
        System.out.println("----filedir = " + filedir);
        for(Socket s : Server.socketList){
            if(!socket.equals(s)){ //转发给其他客户
                BufferedOutputStream bos2 = null;
                try {
                    System.out.println(" 开始创建流");
                    bos2 = new BufferedOutputStream(s.getOutputStream());
                    if(bos2 == null){
                        System.out.println("失败了");
                    }
                    //发送文件
                    //得到文件头byte数组
                    byte[] headers = ParsePack.packFile(filedir);
                    //先发送文件头
                    bos2.write(headers);
                    bos2.flush();

                    //发送文件具体内容
                    String filename = str.substring(5);
                    BufferedInputStream bis =
                            new BufferedInputStream(new FileInputStream(filename));
                    //定义发送文件的数组
                    byte[] data = new byte[1024];
                    int res = 0;
                    //从bis中读取文件内容，放到data中
                    while ( (res = bis.read(data)) != -1){
                        //写入到bos中，发给服务器
                        bos2.write(data,0,res);
                    }
                    bos2.flush();
                    System.out.println("文件转发成功");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }



    }

    /**
     * 把用户的信息转发给其他用户
     * @param pack
     */
    private void refernceMesg(byte[] pack) {
        //遍历整个socket数组
        for(Socket s : Server.socketList){
            if(!socket.equals(s)){ //转发给其他客户
                BufferedOutputStream bos = null;
                try {
                    //synchronized (s) {
                        bos = new BufferedOutputStream(s.getOutputStream());
                        bos.write(pack);
                        bos.flush();
                    //}
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}
